<script lang="ts">
	import { cubicOut } from 'svelte/easing';
	import Icon from '$lib/components/Basic/Icon/Icon.svelte';

	// 类型别名：尺寸值为 lg/md/sm
	type SizeType = 'lg' | 'md' | 'sm';
	// 对齐 Element Plus：支持 boolean/string/number 类型的开关值
	type SwitchValue = boolean | string | number;

	// 事件回调类型定义
	type SwitchEvents = {
		onInput?: (value: SwitchValue) => void;
		onChange?: (value: SwitchValue) => void;
		onClick?: (e: MouseEvent) => void;
	};

	// 组件默认属性值
	const DEFAULT = {
		activeColor: '#1989fa',
		inactiveColor: '#e5e6eb',
		activeIcon: '',
		inactiveIcon: '',
		activeText: '',
		inactiveText: '',
		iconSize: { lg: 16, md: 14, sm: 10 },
		// 对齐 Element Plus：默认激活/关闭值
		activeValue: true as SwitchValue,
		inactiveValue: false as SwitchValue
	} as const;

	// Props（新增 activeValue/inactiveValue）
	let {
		value = $bindable<SwitchValue>(DEFAULT.activeValue),
		size = 'md',
		disabled = false,
		activeColor = DEFAULT.activeColor,
		inactiveColor = DEFAULT.inactiveColor,
		activeText = DEFAULT.activeText,
		inactiveText = DEFAULT.inactiveText,
		activeIcon = DEFAULT.activeIcon,
		inactiveIcon = DEFAULT.inactiveIcon,
		inlinePrompt = $bindable(true),
		name = '',
		id = `el-switch-${Math.random().toString(36).slice(2, 11)}`,
		// 新增：激活/关闭值（对齐 Element Plus）
		activeValue = DEFAULT.activeValue,
		inactiveValue = DEFAULT.inactiveValue,
		onInput = () => {},
		onChange = () => {},
		onClick = () => {},
		...restProps
	} = $props<{
		value?: SwitchValue;
		size?: SizeType;
		disabled?: boolean;
		activeColor?: string;
		inactiveColor?: string;
		activeText?: string;
		inactiveText?: string;
		activeIcon?: string;
		inactiveIcon?: string;
		inlinePrompt?: boolean;
		name?: string;
		id?: string;
		// 新增属性类型定义
		activeValue?: SwitchValue;
		inactiveValue?: SwitchValue;
	} & SwitchEvents>();

	// 内部响应式状态
	let isDisabled = $state(disabled);
	let knobPosition = $state(0);
	let animationFrameId: number | null = null;

	/**
	 * 手动实现过渡动画
	 */
	const tween = (
		from: number,
		to: number,
		duration: number = 200,
		easing: (t: number) => number = cubicOut
	) => {
		const start = performance.now();
		if (animationFrameId) cancelAnimationFrame(animationFrameId);

		const animate = (time: number) => {
			const elapsed = time - start;
			const progress = Math.min(elapsed / duration, 1);
			const easedProgress = easing(progress);
			knobPosition = from + (to - from) * easedProgress;

			if (progress < 1) {
				animationFrameId = requestAnimationFrame(animate);
			} else {
				animationFrameId = null;
			}
		};

		animationFrameId = requestAnimationFrame(animate);
	};

	// 计算属性：判断当前是否为激活状态（对齐 Element Plus：比较 value 与 activeValue）
	const isActive = $derived(value === activeValue);

	// 响应式同步：value 变化触发动画
	$effect(() => {
		if (!isDisabled) {
			tween(knobPosition, isActive ? 1 : 0);
		} else {
			knobPosition = isActive ? 1 : 0;
		}
	});

	// 禁用状态同步
	$effect(() => {
		isDisabled = disabled;
		if (isDisabled) {
			knobPosition = isActive ? 1 : 0;
			if (animationFrameId) {
				cancelAnimationFrame(animationFrameId);
				animationFrameId = null;
			}
		}
	});

	// 组件销毁时取消动画
	$effect(() => {
		return () => {
			if (animationFrameId) cancelAnimationFrame(animationFrameId);
		};
	});

	// 计算属性
	const computedSize = $derived<SizeType>(size);
	const computedIconSize = $derived(DEFAULT.iconSize[computedSize]);
	const computedActiveColor = $derived(isDisabled ? DEFAULT.activeColor : activeColor);
	const computedInactiveColor = $derived(isDisabled ? DEFAULT.inactiveColor : inactiveColor);
	const computedActiveIcon = $derived(isDisabled ? DEFAULT.activeIcon : activeIcon);
	const computedInactiveIcon = $derived(isDisabled ? DEFAULT.inactiveIcon : inactiveIcon);
	const computedActiveText = $derived(isDisabled ? DEFAULT.activeText : activeText);
	const computedInactiveText = $derived(isDisabled ? DEFAULT.inactiveText : inactiveText);

	// 样式计算（根据 isActive 判断，而非直接判断 value）
	const bgColor = $derived(isActive ? computedActiveColor : computedInactiveColor);
	const knobOffset = $derived(size === 'lg' ? 22 : size === 'sm' ? 14 : 18);
	const knobTranslateX = $derived(`${knobPosition * knobOffset}px`);

	/**
	 * 切换开关状态（对齐 Element Plus：切换为 activeValue/inactiveValue）
	 */
	const toggleSwitch = (e: MouseEvent | KeyboardEvent) => {
		if (isDisabled) return;
		// 计算下一个值：当前为激活则切为关闭值，反之则切为激活值
		const nextValue = isActive ? inactiveValue : activeValue;
		value = nextValue;
		// 触发事件（传递新值）
		onInput(nextValue);
		onChange(nextValue);
		onClick(e instanceof MouseEvent ? e : new MouseEvent('click', { bubbles: true }));
	};
</script>

<!-- 外层容器 -->
<div class="el-switch-container" {...restProps}>
	<!-- 左侧区域：inactiveIcon + inactiveText -->
	{#if (!inlinePrompt && computedInactiveIcon) || computedInactiveText}
		<div class="el-switch__left-area" style:font-size={size === 'lg' ? '14px' : size === 'sm' ? '11px' : '12px'}>
			{#if !inlinePrompt && computedInactiveIcon}
				<Icon 
					src={computedInactiveIcon} 
					style={`font-size: ${computedIconSize}px; color: ${isActive ? '#c0c4cc' : '#909399'};`}
					class={`el-switch__icon--outer ${isDisabled ? 'el-switch__icon--disabled' : ''}`}
				/>
			{/if}
			{#if computedInactiveText}
				<span 
					class="el-switch__text el-switch__text--left" 
					class:el-switch__text--disabled={isDisabled}
				>
					{computedInactiveText}
				</span>
			{/if}
		</div>
	{/if}

	<!-- 核心：button 容器 -->
	<button
		type="button"
		class="el-switch"
		class:el-switch--lg={size === 'lg'}
		class:el-switch--md={size === 'md'}
		class:el-switch--sm={size === 'sm'}
		class:el-switch--active={isActive && !isDisabled}
		class:el-switch--disabled={isDisabled}
		style:background-color={bgColor}
		onclick={toggleSwitch}
		{disabled}
		tabindex={isDisabled ? -1 : 0}
		role="switch"
		aria-checked={isActive}
		aria-label={isActive ? '开启' : '关闭'}
	>
		<!-- 滑块 -->
		<div
			class="el-switch__knob"
			style:transform="translateY(-50%) translateX({knobTranslateX})"
		>
			{#if inlinePrompt}
				{#if isActive && computedActiveIcon}
					<span class="el-switch__icon" style={`font-size: ${computedIconSize}px; color: ${computedActiveColor};`}>
						<Icon src={computedActiveIcon} />
					</span>
				{:else if !isActive && computedInactiveIcon}
					<span class="el-switch__icon" style={`font-size: ${computedIconSize}px; color: #909399;`}>
						<Icon src={computedInactiveIcon} />
					</span>
				{/if}
			{/if}
		</div>

		<!-- 表单隐藏输入框（checked 根据 isActive 判断） -->
		<input
			type="checkbox"
			{id}
			{name}
			checked={isActive}
			{disabled}
			class="el-switch__input"
			onchange={(e) => {
				// 1. 先判断 e.target 不为 null
				if (!e.target) return;
				// 2. 断言为 HTMLInputElement 类型（明确包含 checked 属性）
				const input = e.target as HTMLInputElement;
				// 3. 安全访问 checked 属性
				onChange(input.checked ? activeValue : inactiveValue);
			}}
		/>
	</button>

	<!-- 右侧区域：activeText + activeIcon -->
	{#if (!inlinePrompt && computedActiveIcon) || computedActiveText}
		<div class="el-switch__right-area" style:font-size={size === 'lg' ? '14px' : size === 'sm' ? '11px' : '12px'}>
			{#if computedActiveText}
				<span 
					class="el-switch__text el-switch__text--right" 
					class:el-switch__text--disabled={isDisabled}
				>
					{computedActiveText}
				</span>
			{/if}
			{#if !inlinePrompt && computedActiveIcon}
				<Icon 
					src={computedActiveIcon} 
					style={`font-size: ${computedIconSize}px; color: ${isActive ? computedActiveColor : '#c0c4cc'};`}
					class={`el-switch__icon--outer ${isDisabled ? 'el-switch__icon--disabled' : ''}`}
				/>
			{/if}
		</div>
	{/if}
</div>

<style scoped lang="scss">
	.el-switch-container {
		display: inline-flex;
		align-items: center;
		gap: 8px;
	}

	.el-switch__left-area,
	.el-switch__right-area {
		display: inline-flex;
		align-items: center;
		gap: 4px;
		white-space: nowrap;
	}

	.el-switch__icon--outer {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		transition: all 0.2s ease;
	}

	.el-switch__icon--disabled {
		opacity: 0.6;
		cursor: not-allowed;
	}

	.el-switch__text {
		color: #606266;
		user-select: none;
		transition: all 0.2s ease;

		&--disabled {
			opacity: 0.6;
			cursor: not-allowed;
		}
	}

	.el-switch__text--left {
		margin-right: 4px;
	}

	.el-switch__text--right {
		margin-left: 4px;
	}

	// 重置 button 默认样式
	.el-switch {
		position: relative;
		display: inline-block;
		cursor: pointer;
		user-select: none;
		overflow: hidden;
		transition: background-color 0.2s ease, opacity 0.2s ease;
		border-radius: 999px;
		outline: none;
		border: none;
		background: transparent;
		padding: 0;
		margin: 0;
		line-height: 1;

		&:focus-visible {
			outline: 2px solid rgba(25, 137, 250, 0.3);
			outline-offset: 2px;
		}

		&.el-switch--disabled {
			cursor: not-allowed;
			opacity: 0.6;
		}
	}

	// 尺寸样式
	.el-switch--lg {
		width: 50px;
		height: 28px;

		.el-switch__knob {
			width: 24px;
			height: 24px;
		}
	}

	.el-switch--md {
		width: 40px;
		height: 22px;

		.el-switch__knob {
			width: 18px;
			height: 18px;
		}
	}

	.el-switch--sm {
		width: 30px;
		height: 16px;

		.el-switch__knob {
			width: 12px;
			height: 12px;
		}
	}

	.el-switch__knob {
		position: absolute;
		left: 2px;
		top: 50%;
		transform: translateY(-50%);
		border-radius: 50%;
		background-color: #fff;
		box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
		transition: transform 0.2s ease;
		display: flex;
		align-items: center;
		justify-content: center;
		overflow: hidden;

		.el-switch--active & {
			transform: translateX(100%) translateY(-50%);
		}
	}

	.el-switch__icon {
		display: flex;
		align-items: center;
		justify-content: center;
	}

	.el-switch__input {
		display: none;
	}
</style>